package com.ht.file.service;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import com.ht.common.core.exception.ServiceException;
import com.ht.common.core.utils.DateUtils;
import com.ht.common.core.utils.ErrorUtils;
import com.ht.common.core.utils.SnowflakeIdWorker;
import com.ht.common.core.utils.StringUtils;
import com.ht.file.domain.SysAttachFile;
import com.ht.file.mapper.SysAttachFileMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import cn.hutool.core.io.FileUtil;
import javax.imageio.ImageIO;

/**
 * 附件管理Service业务层处理
 *
 * @author zmx
 * @date 2023-01-31
 */
@Service
public class SysAttachFileServiceImpl implements ISysAttachFileService {

    private static final Logger logger = LoggerFactory.getLogger(SysAttachFileServiceImpl.class);
    private final static int MAX_STRING_LENGTH = 204800;

    private String profilePath="D:/mhosp/upload";

    @Autowired
    private SysAttachFileMapper sysAttachFileMapper;

    /**
     * 查询附件管理
     *
     * @param filename 附件管理主键
     * @return 附件管理
     */
    @Override
    public SysAttachFile selectSysAttachFileByFilename(String filename) {
        return sysAttachFileMapper.selectSysAttachFileByFilename(filename);
    }

    /**
     * 查询附件管理列表
     *
     * @param sysAttachFile 附件管理
     * @return 附件管理
     */
    @Override
    public List<SysAttachFile> selectSysAttachFileList(SysAttachFile sysAttachFile) {
        return sysAttachFileMapper.selectSysAttachFileList(sysAttachFile);
    }

    /**
     * 新增附件管理
     *
     * @param sysAttachFile 附件管理
     * @return 结果
     */
    @Override
    public int insertSysAttachFile(SysAttachFile sysAttachFile) {
        sysAttachFile.setCreateTime(DateUtils.getNowDate());
        return sysAttachFileMapper.insertSysAttachFile(sysAttachFile);
    }

    /**
     * 修改附件管理
     *
     * @param sysAttachFile 附件管理
     * @return 结果
     */
    @Override
    public int updateSysAttachFile(SysAttachFile sysAttachFile) {
        return sysAttachFileMapper.updateSysAttachFile(sysAttachFile);
    }

    /**
     * 批量删除附件管理
     *
     * @param filenames 需要删除的附件管理主键
     * @return 结果
     */
    @Override
    public int deleteSysAttachFileByFilenames(String[] filenames) {
        if (StringUtils.isEmpty(filenames)) {
            throw new ServiceException("删除数组为空!");
        }
        int res = 0;
        for (String id : filenames) {
            res += this.deleteSysAttachFileByFilename(id);
        }
        return res;
    }

    /**
     * 删除附件管理信息
     *
     * @param filename 附件管理主键
     * @return 结果
     */
    @Override
    public int deleteSysAttachFileByFilename(String filename) {
        if (StringUtils.isBlank(filename)) {
            throw new ServiceException("参数为空，操作失败!");
        }
        return sysAttachFileMapper.deleteSysAttachFileByFilename(filename);
    }

    @Override
    public void initData() {
        if (StringUtils.isBlank(profilePath)) {
            return;
        }
        List<File> files = FileUtil.loopFiles(profilePath);
        if (StringUtils.isEmpty(files)) {
            return;
        }
        for (File file : files) {
            if (file.isFile()) {
                SysAttachFile dbFile = sysAttachFileMapper.selectSysAttachFileByFilename(file.getName());
                if (null == dbFile) {
                    SysAttachFile saf = new SysAttachFile();
                    saf.setCreateTime(new Date());
                    saf.setExtName(FileUtil.extName(file.getName()));
                    saf.setFullPath(file.getPath());
                    saf.setFilename(file.getName());
                    String ymdDir = file.getPath().substring(profilePath.length() + 1, file.getPath().length() - file.getName().length() - 1);
                    saf.setYmdDir(ymdDir);
                    sysAttachFileMapper.insertSysAttachFile(saf);
                }
            }
        }
    }

    /**
     * 读取文件并转成base64位字符串
     */
    @Override
    public String selectBase64ByFilename(String filename) {
        SysAttachFile dbFile = this.selectSysAttachFileByFilename(filename);
        if (null != dbFile) {
            String fileFullPath = profilePath + File.separator + dbFile.getYmdDir() + File.separator + dbFile.getFilename();
            byte[] fileByte = FileUtil.readBytes(fileFullPath);
            return Base64.getEncoder().encodeToString(fileByte);
        }
        return null;
    }

    @Override
    public String getBase64ResizedImageByFilename(String name) {
        if (StringUtils.isBlank(name)) {
            return "";
        }
        try {
            SysAttachFile saf = this.selectSysAttachFileByFilename(name);
            if (null == saf) {
                logger.error("文件读取失败,未查询到对应文件信息：{}", name);
                return "";
            }
            // 指定图片路径
            File file = new File(saf.getFullPath());
            // 读取图片
            BufferedImage image = ImageIO.read(file);

            // 缩放图片直到其Base64编码长度小于等于MAX_STRING_LENGTH
            BufferedImage resizedImage = resizeImage(image, saf.getExtName());
            if (null == resizedImage) {
                logger.error("缩放图片直到其Base64编码长度小于等于MAX_STRING_LENGTH结果为空：{}", name);
                return "";
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(resizedImage, saf.getExtName(), baos);
            baos.flush();
            byte[] imageData = baos.toByteArray();
            baos.close();
            return Base64.getEncoder().encodeToString(imageData);
        } catch (IOException e) {
            logger.error("文件地址读取失败：{}", name);
            ErrorUtils.printErr(e);
            return "";
        }
    }


    /**
     * 同步文件到本地
     *
     * @param picBase64
     */
    @Override
    public String syncPicSaveLocal(String picBase64) {
        SysAttachFile sysFile = new SysAttachFile();
        String ymdDir = DateUtils.datePath();
        String dirPath =profilePath + File.separator + ymdDir;
        checkDir(dirPath);
        String fileName = SnowflakeIdWorker.getUUID() + "." + "jpg";
        dirPath = dirPath + File.separator + fileName;
        dirPath = dirPath.replace("\\", "/");

        byte[] picByte = Base64.getDecoder().decode(picBase64);
        File file = new File(dirPath);
        FileUtil.writeBytes(picByte, file);

        sysFile.setCreateTime(new Date());
        sysFile.setFilename(fileName);
        sysFile.setFullPath(dirPath);
        sysFile.setExtName(FileUtil.extName(fileName));
        sysFile.setYmdDir(ymdDir);
        //file
        sysFile.setSize((long) picByte.length);
        this.insertSysAttachFile(sysFile);
        return fileName;
    }

    private void checkDir(String dir) {
        File dirs = new File(dir);
        if (!dirs.exists()) {
            dirs.mkdirs();
        }
    }

    /**
     * 图片压缩
     *
     * @param originalImage
     * @param extName
     * @return BufferedImage
     * @author dyg
     * @date 2024/6/17 11:25
     */
    private static BufferedImage resizeImage(BufferedImage originalImage, String extName) throws IOException {
        double scale = 1.0;
        String dataURI;
        BufferedImage resizedImage;
        do {
            // 缩放图片
            int newWidth = (int) (originalImage.getWidth() * scale);
            int newHeight = (int) (originalImage.getHeight() * scale);
            Image tmp = originalImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
            resizedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = resizedImage.createGraphics();
            g2d.drawImage(tmp, 0, 0, null);
            g2d.dispose();

            // 将缩放后的图片转换为Base64编码
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(resizedImage, extName, baos);
            baos.flush();
            byte[] imageData = baos.toByteArray();
            baos.close();
            dataURI = Base64.getEncoder().encodeToString(imageData);
            // 减少缩放比例
            scale -= 0.1;

        } while (dataURI.length() > MAX_STRING_LENGTH && scale > 0);

        return scale > 0 ? resizedImage : null;
    }
    @Override
    public SysAttachFile selectByFilename(String filename) {
        return this.selectSysAttachFileByFilename(filename);
    }
}
